package com.tms.control;

import com.github.pagehelper.PageInfo;
import com.tms.domain.Position;
import com.tms.domain.User;
import com.tms.domain.Workcell;
import com.tms.service.PositionService;
import com.tms.service.UserService;
import com.tms.service.WorkcellService;
import com.tms.utils.Data;
import com.tms.utils.JsonResult;
import com.tms.utils.token.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.tms.core.constants.UserConstants.*;
/**
 * 用户
 */
@RestController
@RequestMapping("/api/users")
public class UserController extends BaseController {

    @Autowired
    private UserService userService;

    @Autowired
    private PositionService positionService;

    @Autowired
    private WorkcellService workcellService;

    @Autowired
    private TokenService tokenService;

    private BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();


    /**
     * 修改用户邮箱或者密码
     *
     * @param map 表单数据，size为1修改邮箱，size为3修改密码
     * @param req Http请求
     * @return 成功返回success、user，失败返回failed并说明理由
     */
    @PatchMapping
    public JsonResult update(@RequestBody Map<String, String> map, HttpServletRequest req) {
        JsonResult result;
        User user = tokenService.getUserByRequest(req);
        if (user == null) {
            result = new JsonResult(ERROR_NULL_USER.getStatus(), ERROR_NULL_USER.getDesc());
        } else if (map.size() == 1) {
            //修改邮箱
            String email = map.get("email");
            //判断邮箱是否为空，格式是否正确
            if (email == null) {
                result = new JsonResult(ERROR_NULL_EMAIL.getStatus(), ERROR_NULL_EMAIL.getDesc());
            } else if (!isEmail(email)) {
                result = new JsonResult(ERROR_FORMAT_EMAIL.getStatus(), ERROR_FORMAT_EMAIL.getDesc());
            } else {
                user.setEmail(email);
                //更新
                userService.updateUserById(user);
                result = new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(user));
            }
        } else {
            //修改密码
            String oldPwd = map.get("oldpwd");
            String newPwd = map.get("newpwd");
            String confirmPwd = map.get("confirmpwd");
            //旧密码加密后与数据库密码匹配
            //判断取得的新旧密码是否为空
            //判断两次新密码是否一致
            if (!bCryptPasswordEncoder.matches(oldPwd, user.getPwd())) {
                result = new JsonResult(ERROR_PWD.getStatus(), ERROR_PWD.getDesc());
            } else if (newPwd == null || newPwd.length() == 0 || confirmPwd == null || confirmPwd.length() == 0) {
                result = new JsonResult(ERROR_NULL_PWD.getStatus(), ERROR_NULL_PWD.getDesc());
            } else if (!newPwd.equals(confirmPwd)) {
                result = new JsonResult(ERROR_CONFIRMPWD.getStatus(), ERROR_CONFIRMPWD.getDesc());
            } else {
                //密码加密
                user.setPwd(bCryptPasswordEncoder.encode(confirmPwd));
                //更新
                userService.updateUserById(user);
                String token = tokenService.getToken(user);
                result = new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(user.getNo(), token, user));
            }
        }
        return result;
    }

    @PostMapping("/login")
    public JsonResult login(@RequestParam(value = "username") String userName,
                            @RequestParam(value = "password") String password,
                            @RequestParam(value = "workcellId") int workcellId) {
        JsonResult result;
        //取得的参数进行判断是否为空
        if (userName == null || userName.length() == 0) {
            result = new JsonResult(ERROR_NULL_USERNAME.getStatus(), ERROR_NULL_USERNAME.getDesc());
        } else if (password == null || password.length() == 0) {
            result = new JsonResult(ERROR_NULL_PWD.getStatus(), ERROR_NULL_PWD.getDesc());
        } else {
            //通过username和workcellId获取用户
            User user = userService.findUserByNoAndWorkcell(userName, workcellId);
            //判断用户是否存在
            //判断密码是否匹配，匹配则生成token返回
            if (user == null) {
                result = new JsonResult(ERROR_NULL_USER.getStatus(), ERROR_NULL_USER.getDesc());
            } else if (bCryptPasswordEncoder.matches(password, user.getPwd())) {
                String token = tokenService.getToken(user);
                result = new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(),
                        new Data(user.getNo(), token, user));
            } else {
                result = new JsonResult(ERROR_PWD.getStatus(), ERROR_PWD.getDesc());
            }
        }
        return result;
    }

    @PostMapping
    public JsonResult addUser(@RequestBody Map<String, String> map) {
        JsonResult result;
        //取出需要的参数
        int workcellId = Integer.parseInt(map.get("workcell"));
        String no = map.get("no");
        String name = map.get("name");
        String pwd = map.get("pwd");
        String positionName = map.get("position");
        String email = map.get("email");
        String phone = map.get("phone");
        //对他们进行判空操作并判断相应的position，workcell是否存在
        if (no != null) {
            //该用户名不存在该workcell
            if (userService.findUserByNoAndWorkcell(no, workcellId) == null) {
                //密码不为空
                if (pwd != null && pwd.length() != 0) {
                    Workcell workcell = workcellService.findWorkcellById(workcellId);
                    //存在该workcell
                    if (workcell != null) {
                        Position position = positionService.findPositionByName(positionName);
                        //存在该position
                        if (position != null) {
                            //用户 名字不为空
                            if (name != null && name.length() != 0) {
                                User user = new User(no, name, email, phone, bCryptPasswordEncoder.encode(pwd), workcell, position);
                                userService.createUser(user);
                                //判断是否插入成功
                                if (user.getId() != 0) {
                                    result = new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(user.getNo(), tokenService.getToken(user), user));
                                } else {
                                    result = new JsonResult(ERROR.getStatus(), ERROR.getDesc());
                                }
                            } else {
                                result = new JsonResult(ERROR_NULL_NAME.getStatus(), ERROR_NULL_NAME.getDesc());
                            }
                        } else {
                            result = new JsonResult(ERROR_NULL_POSITION.getStatus(), ERROR_NULL_POSITION.getDesc());
                        }
                    } else {
                        result = new JsonResult(ERROR_NULL_WORKCELL.getStatus(), ERROR_NULL_WORKCELL.getDesc());
                    }
                } else {
                    result = new JsonResult(ERROR_NULL_PWD.getStatus(), ERROR_NULL_PWD.getDesc());
                }
            } else {
                result = new JsonResult(ERROR_EXIST_USERNAME.getStatus(), ERROR_EXIST_USERNAME.getDesc());
            }
        } else {
            result = new JsonResult(ERROR_NULL_USERNAME.getStatus(), ERROR_NULL_USERNAME.getDesc());
        }
        return result;
    }

    /**
     * 通过no删除用户，即修改deletion为 0
     *
     * @param id 用户id
     * @return 成功返回success，失败返回failed
     * @author Liao
     */
    @DeleteMapping("{id}")
    public JsonResult deleteUser(@PathVariable("id") int id, HttpServletRequest req) {
        JsonResult result;
        int workcellId = tokenService.getWorkcellId(request);
        User user = userService.findUserById(id);
        User admin = tokenService.getUserByRequest(req);
        if (user == null) {
            result = new JsonResult(ERROR_NULL_USER.getStatus(), ERROR_NULL_USER.getDesc());
        } else if (admin == null) {
            result = new JsonResult(ERROR_TOKEN.getStatus(), ERROR_TOKEN.getDesc());
        } else if (workcellId != user.getWorkcell().getId()) {
            result = new JsonResult(ERROR_OTHER_WORKCELL.getStatus(), ERROR_OTHER_WORKCELL.getDesc());
        } else {
            String no = user.getNo();
            userService.deleteUserByNoAndWorkcellId(no, workcellId);
            user = userService.findUserByNoAndWorkcell(no, workcellId);
            if (user == null) {
                result = new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(id));
            } else {
                result = new JsonResult(ERROR_DELETE.getStatus(), ERROR_DELETE.getDesc());
            }
        }
        return result;
    }

    /**
     * 修改用户position
     *
     * @param no  用户no
     * @param map 表单数据size为1，值为新的position
     * @return 成功返回success、token、user，失败返回failed并说明理由
     * @author Liao
     */
    @PatchMapping("/{no}")
    public JsonResult updatePosition(@PathVariable("no") String no, @RequestBody Map<String, String> map, HttpServletRequest req) {
        JsonResult result;
        int workcellId = tokenService.getWorkcellId(request);
        User user = userService.findUserByNoAndWorkcell(no, workcellId);
        if (user == null) {
            result = new JsonResult(ERROR_NULL_USER.getStatus(), ERROR_NULL_USER.getDesc());
        } else {
            String name = map.get("position");
            if (name == null) {
                result = new JsonResult(ERROR_NULL_POSITION.getStatus(), ERROR_NULL_POSITION.getDesc());
            } else {
                Position position = positionService.findPositionByName(name);
                //判断该position是否存在
                if (position == null) {
                    result = new JsonResult(ERROR_POSITION.getStatus(), ERROR_POSITION.getDesc());
                } else {
                    user.setPosition(position);
                    //更新user
                    userService.updateUserById(user);
                    result = new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(user));
                }
            }
        }
        return result;
    }


    /**
     * 解析用户token并返回user信息
     *
     * @param req HTTPRequest
     * @return 成功返回success、token、user对象，失败返回failed、原因
     */
    @GetMapping("/currentUser")
    public JsonResult getUserByToken(HttpServletRequest req) {
        JsonResult result;
        User user = tokenService.getUserByRequest(req);
        if (user == null) {
            result = new JsonResult(ERROR_NULL_USER.getStatus(), ERROR_NULL_USER.getDesc());
        } else {
            result = new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data(user));
        }
        return result;
    }


    @GetMapping
    public JsonResult getUserByWorkcell(@RequestParam(value = "page", defaultValue = "1") int page,
                                        @RequestParam(value = "pageSize", defaultValue = "5") int pageSize,
                                        @RequestParam(value = "workcell") int workcellId) {
        JsonResult result;
        Workcell workcell = workcellService.findWorkcellById(workcellId);
        if (workcell == null) {
            result = new JsonResult(ERROR_NULL_WORKCELL.getStatus(), ERROR_NULL_WORKCELL.getDesc());
        } else {
            PageInfo<User> info = userService.findUsersByWorkcellId(page, pageSize, workcell);
            result = new JsonResult(SUCCESS.getStatus(), SUCCESS.getDesc(), new Data("users", info));
        }
        return result;
    }


    /**
     * 检测邮箱地址是否合法
     *
     * @param email 需验证的邮箱
     * @return true合法 false不合法
     */
    private static boolean isEmail(String email) {
        if (email == null) {
            return false;
        }
        String rule = "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?";
        Pattern pattern;
        Matcher matcher;
        pattern = Pattern.compile(rule);
        matcher = pattern.matcher(email);
        return matcher.matches();
    }
}